//|||||||||||||||||||||||||||||||||||||||||||||||

#include "GameState.h"

#include "KeyManager.h"

//|||||||||||||||||||||||||||||||||||||||||||||||

using namespace Ogre;

//|||||||||||||||||||||||||||||||||||||||||||||||

GameState::GameState()
{
    m_MoveSpeed		= 0.1f;
    m_RotateSpeed	= 0.3f;

    m_bLMouseDown       = false;
    m_bRMouseDown       = false;
    m_bQuit             = false;
    m_bSettingsMode     = false;

    m_pDetailsPanel	= 0;

    m_gameManager = 0;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void GameState::enter()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering GameState...");

    m_pSceneMgr = OgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "GameSceneMgr");
    m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7f, 0.7f, 0.7f));

    m_pRSQ = m_pSceneMgr->createRayQuery(Ray());
    m_pRSQ->setQueryMask(QUERY_BLOCK);

    m_pCamera = m_pSceneMgr->createCamera("GameCamera");
    m_pCamera->setPosition(Vector3(5, 8, 10));
    m_pCamera->lookAt(Vector3(5, 0, 9));
    m_pCamera->setNearClipDistance(0.01);

    m_pCamera->setAspectRatio(Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualWidth()) /
                              Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualHeight()));

    OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);
    m_pCurrentObject = 0;



    GameManager::getInstance()->init();


    GameManager::getInstance()->getObjectMgrPtr()->createObject("worker2","worker",Ogre::Vector2(5,5));


    GameManager::getInstance()->getObjectMgrPtr()->createObject("builder","builder",Ogre::Vector2(4,4));
  //  GameManager::getInstance()->getObjectMgrPtr()->createObject("worker","worker",Ogre::Vector2(4,5));

  //  GameManager::getInstance()->getObjectMgrPtr()->createObject("stock","stock",Ogre::Vector2(3,5));
  //  GameManager::getInstance()->getObjectMgrPtr()->createObject("sandPile","sandPile",Ogre::Vector2(8,6));

  //  GameManager::getInstance()->getObjectMgrPtr()->createObject("sand","sand",Ogre::Vector2(8.2,6.7));



    createScene();


    buildGUI();






}

bool GameState::pause()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Pausing GameState...");

    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void GameState::resume()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Resuming GameState...");

    buildGUI();

    OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);
    m_bQuit = false;
}

void GameState::exit()
{


    GameManager::getInstance()->clear();



    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Leaving GameState...");

    m_pSceneMgr->destroyCamera(m_pCamera);
    m_pSceneMgr->destroyQuery(m_pRSQ);
    if(m_pSceneMgr)
        OgreFramework::getSingletonPtr()->m_pRoot->destroySceneManager(m_pSceneMgr);



}

void GameState::createScene()
{
    m_pSceneMgr->createLight("Light")->setPosition(75,75,75);



}

bool GameState::keyPressed(const OIS::KeyEvent &keyEventRef)
{
    if(m_bSettingsMode == true)
    {
        if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_S))
        {
            OgreBites::SelectMenu* pMenu = (OgreBites::SelectMenu*)OgreFramework::getSingletonPtr()->m_pTrayMgr->getWidget("ChatModeSelMenu");
            if(pMenu->getSelectionIndex() + 1 < (int)pMenu->getNumItems())
                pMenu->selectItem(pMenu->getSelectionIndex() + 1);
        }

        if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_W))
        {
            OgreBites::SelectMenu* pMenu = (OgreBites::SelectMenu*)OgreFramework::getSingletonPtr()->m_pTrayMgr->getWidget("ChatModeSelMenu");
            if(pMenu->getSelectionIndex() - 1 >= 0)
                pMenu->selectItem(pMenu->getSelectionIndex() - 1);
        }
    }

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
    {
        pushAppState(findByName("PauseState"));
        return true;
    }

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_E))
    {

        /*        Ogre::Vector2 p = GameManager::getInstance()->getObjectMgrPtr()->getPlayer()->getPosition();
                p.x=float(int(p.x+0.5));
         p.y=float(int(p.y+0.5));
                GameManager::getInstance()->createBuilding("House3",p );*/

    }

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_I))
    {
        if(m_pDetailsPanel->getTrayLocation() == OgreBites::TL_NONE)
        {
            OgreFramework::getSingletonPtr()->m_pTrayMgr->moveWidgetToTray(m_pDetailsPanel, OgreBites::TL_TOPLEFT, 0);
            m_pDetailsPanel->show();
        }
        else
        {
            OgreFramework::getSingletonPtr()->m_pTrayMgr->removeWidgetFromTray(m_pDetailsPanel);
            m_pDetailsPanel->hide();
        }
    }

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_TAB))
    {
        m_bSettingsMode = !m_bSettingsMode;
        return true;
    }

    if(m_bSettingsMode && OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_RETURN) ||
            OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_NUMPADENTER))
    {
    }

    if(!m_bSettingsMode || (m_bSettingsMode && !OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_O)))
        OgreFramework::getSingletonPtr()->keyPressed(keyEventRef);

    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool GameState::keyReleased(const OIS::KeyEvent &keyEventRef)
{
    OgreFramework::getSingletonPtr()->keyPressed(keyEventRef);
    return true;
}


bool GameState::mouseMoved(const OIS::MouseEvent &evt)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseMove(evt)) return true;

     //  OgreFramework::getSingletonPtr()->m_pLog->logMessage("Mouse wheel : " + Ogre::StringConverter::toString(evt.state.Z.rel));
   m_pCamera->move(Ogre::Vector3(0.00,evt.state.Z.rel*0.001,0.0));

    /*
        if(m_bRMouseDown)
        {
            m_pCamera->yaw(Degree(evt.state.X.rel * -0.1f));
            m_pCamera->pitch(Degree(evt.state.Y.rel * -0.1f));
        }*/

    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool GameState::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseDown(evt, id)) return true;

    if(id == OIS::MB_Left)
    {
        onLeftPressed(evt);
        m_bLMouseDown = true;
    }
    else if(id == OIS::MB_Right)
    {
        onRightPressed(evt);
        m_bRMouseDown = true;
    }



    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool GameState::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{


    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseUp(evt, id)) return true;

    if(id == OIS::MB_Left)
    {
        m_bLMouseDown = false;
    }
    else if(id == OIS::MB_Right)
    {
        m_bRMouseDown = false;
    }




    return true;
}

void GameState::onLeftPressed(const OIS::MouseEvent &evt)
{
    if(m_pCurrentObject)
    {
        m_pCurrentObject->showBoundingBox(false);

    }

    Ogre::Ray mouseRay = m_pCamera->getCameraToViewportRay(OgreFramework::getSingletonPtr()->m_pMouse->getMouseState().X.abs / float(evt.state.width),
                         OgreFramework::getSingletonPtr()->m_pMouse->getMouseState().Y.abs / float(evt.state.height));
    m_pRSQ->setRay(mouseRay);
    m_pRSQ->setSortByDistance(true);
    m_pRSQ->setQueryMask(QUERY_BLOCK | QUERY_BUILDING | QUERY_CHARACTER);

    Ogre::RaySceneQueryResult &result = m_pRSQ->execute();
    Ogre::RaySceneQueryResult::iterator itr;



    for(itr = result.begin(); itr != result.end(); itr++)
    {

        if(itr->movable)
        {


            OgreFramework::getSingletonPtr()->m_pLog->logMessage("MovableName: " + itr->movable->getName());
            m_pCurrentObject = m_pSceneMgr->getEntity(itr->movable->getName())->getParentSceneNode();
            m_pCurrentObject->showBoundingBox(true);




            break;
        }
    }
    std::pair<bool,Ogre::Real> pair;

    pair = mouseRay.intersects(Ogre::Plane(Ogre::Vector3::UNIT_Y,0.0));
    Ogre::Vector2 posAtGround = Ogre::Vector2(mouseRay.getPoint(pair.second).x,mouseRay.getPoint(pair.second).z);


    if(m_pCurrentObject)
    {
        Ogre::Vector2 p = Ogre::Vector2(m_pCurrentObject->getPosition().x,m_pCurrentObject->getPosition().z);

        m_pDetailsPanel->setParamValue(0,m_pCurrentObject->getName());
        m_pDetailsPanel->setParamValue(1, Ogre::StringConverter::toString(p.x));
        m_pDetailsPanel->setParamValue(2, Ogre::StringConverter::toString(p.y));


    Object* obj= GameManager::getInstance()->getObjectMgrPtr()->getObjectFromName(m_pCurrentObject->getName());
            if (obj!=0)
            {
                GameManager::getInstance()->getObjectMgrPtr()->setPlayer(obj);
            }
/*
        if (GameManager::getInstance()->getLevelMgrPtr()->isBlockCrossable(p.x,p.y))
        {
            m_pDetailsPanel->setParamValue(3, "Crossable");

            //  Ogre::ParticleSystem* particle = m_pSceneMgr->createParticleSystem("Sun", "Examples/GreenyNimbus");
            //  particle->getEmitter(0)->setPosition(Ogre::Vector3(posAtGround.x,0,posAtGround.y));

        }
        else
        {
            m_pDetailsPanel->setParamValue(3, "Non Crossable");
        }*/
    }
}


void GameState::onRightPressed(const OIS::MouseEvent &evt)
{


    Ogre::Ray mouseRay = m_pCamera->getCameraToViewportRay(OgreFramework::getSingletonPtr()->m_pMouse->getMouseState().X.abs / float(evt.state.width),
                         OgreFramework::getSingletonPtr()->m_pMouse->getMouseState().Y.abs / float(evt.state.height));
    m_pRSQ->setRay(mouseRay);
    m_pRSQ->setSortByDistance(true);
    m_pRSQ->setQueryMask(QUERY_BLOCK);

    Ogre::RaySceneQueryResult &result = m_pRSQ->execute();
    Ogre::RaySceneQueryResult::iterator itr;


    Ogre::SceneNode* currentObj=0;
    for(itr = result.begin(); itr != result.end(); itr++)
    {
        if(itr->movable)
        {


            OgreFramework::getSingletonPtr()->m_pLog->logMessage("MovableName: " + itr->movable->getName());
            currentObj = m_pSceneMgr->getEntity(itr->movable->getName())->getParentSceneNode();
            // m_pCurrentObject->showBoundingBox(true);

            break;
        }
    }
    std::pair<bool,Ogre::Real> pair;

    pair = mouseRay.intersects(Ogre::Plane(Ogre::Vector3::UNIT_Y,0.0));
    Ogre::Vector2 posAtGround = Ogre::Vector2(mouseRay.getPoint(pair.second).x,mouseRay.getPoint(pair.second).z);


    if(currentObj)
    {
        Ogre::Vector2 p = Ogre::Vector2(currentObj->getPosition().x,currentObj->getPosition().z);

        if (GameManager::getInstance()->getLevelMgrPtr()->isBlockCrossable(p.x,p.y))
        {
            GameManager::getInstance()->getObjectMgrPtr()->giveOrderToGoTo(posAtGround);

        }
        else
        {

        }
    }
}

void GameState::moveCamera()
{

    //  Ogre::Vector3 p = GameManager::getInstance()->getObjectMgrPtr()->getPlayer()->getSceneNode()->getPosition();
    //  m_pCamera->setPosition(p+Ogre::Vector3(0,5,-5));
    //  m_pCamera->lookAt(p);
    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(KeyManager::getInstance()->getKeyCode("moveCameraUp")))
        m_pCamera->move(Ogre::Vector3(0,0.00,-0.05));

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(KeyManager::getInstance()->getKeyCode("moveCameraDown")))
        m_pCamera->move(Ogre::Vector3(0,0.00,0.05));

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(KeyManager::getInstance()->getKeyCode("moveCameraLeft")))
        m_pCamera->move(Ogre::Vector3(-0.05,0.0,0.0));

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(KeyManager::getInstance()->getKeyCode("moveCameraRight")))
        m_pCamera->move(Ogre::Vector3(0.05,0.0,0.0));

}

void GameState::getInput()
{
    if(m_bSettingsMode == false)
    {
        if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_A))
            m_TranslateVector.x = -m_MoveScale;

        if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_D))
            m_TranslateVector.x = m_MoveScale;

        if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_W))
            m_TranslateVector.z = -m_MoveScale;

        if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_S))
            m_TranslateVector.z = m_MoveScale;
    }
}

void GameState::update(double timeSinceLastFrame)
{
    m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;
    OgreFramework::getSingletonPtr()->m_pTrayMgr->frameRenderingQueued(m_FrameEvent);

    if(m_bQuit == true)
    {
        popAppState();
        return;
    }

    if(!OgreFramework::getSingletonPtr()->m_pTrayMgr->isDialogVisible())
    {
        if(m_pDetailsPanel->isVisible())
        {

            /*
                        if(m_bSettingsMode)
                            m_pDetailsPanel->setParamValue(2, "Buffered Input");
                        else
                            m_pDetailsPanel->setParamValue(2, "Un-Buffered Input");*/
        }
    }

    m_MoveScale = m_MoveSpeed   * timeSinceLastFrame;
    m_RotScale  = m_RotateSpeed * timeSinceLastFrame;

    m_TranslateVector = Vector3::ZERO;

    getInput();
    moveCamera();

    GameManager::getInstance()->update(timeSinceLastFrame);
}

void GameState::buildGUI()
{
    OgreFramework::getSingletonPtr()->m_pTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);
    // OgreFramework::getSingletonPtr()->m_pTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->createLabel(OgreBites::TL_TOP, "GameLbl", "Game mode", 250);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->showCursor();

    Ogre::StringVector items;
    items.push_back("Name");
    items.push_back("X");
    items.push_back("Y");

    items.push_back("Mode");

    m_pDetailsPanel = OgreFramework::getSingletonPtr()->m_pTrayMgr->createParamsPanel(OgreBites::TL_TOPLEFT, "DetailsPanel", 200, items);
    // m_pDetailsPanel->show();
    /*
        Ogre::String infoText = "[TAB] - Switch input mode\n\n[W] - Forward / Mode up\n[S] - Backwards/ Mode down\n[A] - Left\n";
        infoText.append("[D] - Right\n\nPress [SHIFT] to move faster\n\n[O] - Toggle FPS / logo\n");
        infoText.append("[Print] - Take screenshot\n\n[ESC] - Exit");
        OgreFramework::getSingletonPtr()->m_pTrayMgr->createTextBox(OgreBites::TL_RIGHT, "InfoPanel", infoText, 300, 220);*/


}

void GameState::itemSelected(OgreBites::SelectMenu* menu)
{
    switch(menu->getSelectionIndex())
    {
    case 0:

        break;
    }
}
